﻿#include "FramelessWindow.h"
#include <QGraphicsDropShadowEffect>
#include <QScreen>
#include <QStyle>
#include <QMenuBar>
#include <QStatusBar>
#include <QTextEdit>
#include <QTimer>
#include <QApplication>

FramelessWindow::FramelessWindow(QWidget* parent) :
    QWidget(parent, Qt::FramelessWindowHint | Qt::WindowMinMaxButtonsHint)
{
    setAttribute(Qt::WA_TranslucentBackground);
    setupUi();
    setupWindowControls();
    setWindowTitle("Frameless Window Demo");
    resize(800, 600);

    // 添加阴影效果
    auto* shadowEffect = new QGraphicsDropShadowEffect(this);
    shadowEffect->setBlurRadius(15);
    shadowEffect->setColor(QColor(0, 0, 0, 150));
    shadowEffect->setOffset(0, 0);
    this->setGraphicsEffect(shadowEffect);
    this->setMouseTracking(true);
}

void FramelessWindow::setIcon(const QString& icon)
{
    m_icon_label->setPixmap(QIcon(icon).pixmap(16, 16));
}

void FramelessWindow::setTitle(const QString& title)
{
    m_title_label->setText(title);
}

void FramelessWindow::setHeadBackgroundColor(const QString& color)
{
    m_head_widget->setStyleSheet(QString("#head { background:%1; }").arg(color));
    qDebug() << m_head_widget->styleSheet();
    this->update();
}

void FramelessWindow::setContentWidget(QWidget* widget)
{
    if (m_body_layout->count() > 0)
    {
        QLayoutItem* item = m_body_layout->takeAt(0);
        if (item && item->widget())
        {
            item->widget()->setParent(nullptr);
        }
        delete item;
    }
    m_body_layout->addWidget(widget);
}

void FramelessWindow::hideMaximizeButton(bool hidden)
{
    m_max_button->setVisible(!hidden);
}

void FramelessWindow::hideMinimizeButton(bool hidden)
{
    m_min_button->setVisible(!hidden);
}

void FramelessWindow::hideCloseButton(bool hidden)
{
    m_close_button->setVisible(!hidden);
}

void FramelessWindow::hideIcon(bool hidden)
{
    m_icon_label->setVisible(!hidden);
}

void FramelessWindow::hideTitle(bool hidden)
{
    m_title_label->setVisible(!hidden);
}

void FramelessWindow::mousePressEvent(QMouseEvent* event)
{
    QWidget::mousePressEvent(event);
    if (event->button() == Qt::LeftButton)
    {
        m_dragPosition = event->globalPosition().toPoint() - frameGeometry().topLeft();
        if (isInResizeArea(event->pos()))
        {
            m_resizing = true;
            m_resizeStartPos = event->globalPosition().toPoint();
            m_resizeStartGeometry = geometry();
        }
        else if (isInTitleBarArea(event->position()))
        {
            m_dragging = true;
        }
        // event->accept();
    }
}

void FramelessWindow::mouseReleaseEvent(QMouseEvent* event)
{
    QWidget::mouseReleaseEvent(event);
    if (event->button() == Qt::LeftButton)
    {
        m_dragging = false;
        m_resizing = false;
        updateCursorShape(event->position());
    }
}

void FramelessWindow::mouseDoubleClickEvent(QMouseEvent* event)
{
    QWidget::mouseDoubleClickEvent(event);
    if (isInTitleBarArea(event->position()))
    {
        toggleMaximize();
    }
}

void FramelessWindow::mouseMoveEvent(QMouseEvent* event)
{
    QWidget::mouseMoveEvent(event);
    if (event->buttons() & Qt::LeftButton)
    {
        if (m_dragging)
        {
            if (isMaximized())
            {
                double x_factory = 1.0 - (double)(width() - m_dragPosition.x()) / width();
                double y_facotry = 1.0 - (double)(height() - m_dragPosition.y()) / height();
                toggleMaximize();
                QPointF new_pos = QPointF(width() * x_factory, height() * y_facotry);
                move((event->globalPosition() - new_pos).toPoint());
                m_dragPosition = event->globalPosition().toPoint() - frameGeometry().topLeft();
            }
            else
            {
                move(event->globalPosition().toPoint() - m_dragPosition);
            }
        }
        else if (m_resizing)
        {
            QPoint delta = event->globalPosition().toPoint() - m_resizeStartPos;
            QRect newGeometry = m_resizeStartGeometry;

            switch (m_resizeEdge)
            {
            case TopLeft:
                newGeometry.setTopLeft(newGeometry.topLeft() + delta);
                break;
            case Top:
                newGeometry.setTop(newGeometry.top() + delta.y());
                break;
            case TopRight:
                newGeometry.setTopRight(newGeometry.topRight() + delta);
                break;
            case Right:
                newGeometry.setRight(newGeometry.right() + delta.x());
                break;
            case BottomRight:
                newGeometry.setBottomRight(newGeometry.bottomRight() + delta);
                break;
            case Bottom:
                newGeometry.setBottom(newGeometry.bottom() + delta.y());
                break;
            case BottomLeft:
                newGeometry.setBottomLeft(newGeometry.bottomLeft() + delta);
                break;
            case Left:
                newGeometry.setLeft(newGeometry.left() + delta.x());
                break;
            default:
                break;
            }

            // 限制最小尺寸
            if (newGeometry.width() < minimumWidth())
            {
                if (m_resizeEdge == Left || m_resizeEdge == TopLeft || m_resizeEdge == BottomLeft)
                {
                    newGeometry.setLeft(newGeometry.right() - minimumWidth());
                }
                else
                {
                    newGeometry.setRight(newGeometry.left() + minimumWidth());
                }
            }

            if (newGeometry.height() < minimumHeight())
            {
                if (m_resizeEdge == Top || m_resizeEdge == TopLeft || m_resizeEdge == TopRight)
                {
                    newGeometry.setTop(newGeometry.bottom() - minimumHeight());
                }
                else
                {
                    newGeometry.setBottom(newGeometry.top() + minimumHeight());
                }
            }

            setGeometry(newGeometry);
            m_resizeStartPos = event->globalPosition().toPoint();
            m_resizeStartGeometry = geometry();
        }
    }
    else
    {
        updateCursorShape(event->position());
    }
}

void FramelessWindow::minimizeWindow()
{
    showMinimized();
}

void FramelessWindow::toggleMaximize()
{
    if (isMaximized())
    {
        m_layout->setContentsMargins(MarginSize, MarginSize, MarginSize, MarginSize);
        showNormal();
        m_max_button->setIcon(style()->standardIcon(QStyle::SP_TitleBarMaxButton));
    }
    else
    {
        m_layout->setContentsMargins(0, 0, 0, 0);
        showMaximized();
        m_max_button->setIcon(style()->standardIcon(QStyle::SP_TitleBarNormalButton));
    }
}

void FramelessWindow::closeWindow()
{
    close();
}

void FramelessWindow::setupUi()
{
    m_main_widget = new QWidget(this);

    m_head_widget = new QWidget(m_main_widget);
    m_head_widget->setObjectName("head");
    m_head_widget->setStyleSheet("#head { background:blue; }");
    m_head_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    m_head_widget->setFixedHeight(36);

    m_body_widget = new QWidget(m_main_widget);
    m_body_widget->setObjectName("body");
    m_body_widget->setStyleSheet("#body { background:white; }");
    m_body_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    m_foot_widget = new QWidget(m_main_widget);
    m_foot_widget->setObjectName("foot");
    m_foot_widget->setStyleSheet("#body { background:white; }");
    m_foot_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

    m_icon_label = new QLabel(m_head_widget);
    m_icon_label->setPixmap(style()->standardIcon(QStyle::SP_ComputerIcon).pixmap(16, 16));

    m_title_label = new QLabel("Frameless Window", m_head_widget);
    m_title_label->setStyleSheet("color: white; font-weight: bold;");

    m_min_button = new QPushButton(m_head_widget);
    m_min_button->setIcon(style()->standardIcon(QStyle::SP_TitleBarMinButton));
    m_min_button->setFixedSize(30, 30);
    m_min_button->setStyleSheet("QPushButton { border: none; background: transparent; }"
                                "QPushButton:hover { background-color: #2980b9; }");

    m_max_button = new QPushButton(m_head_widget);
    m_max_button->setIcon(style()->standardIcon(QStyle::SP_TitleBarMaxButton));
    m_max_button->setFixedSize(30, 30);
    m_max_button->setStyleSheet("QPushButton { border: none; background: transparent; }"
                                "QPushButton:hover { background-color: #2980b9; }");

    m_close_button = new QPushButton(m_head_widget);
    m_close_button->setIcon(style()->standardIcon(QStyle::SP_TitleBarCloseButton));
    m_close_button->setFixedSize(30, 30);
    m_close_button->setStyleSheet("QPushButton { border: none; background: transparent; }"
                                  "QPushButton:hover { background-color: #e74c3c; }");

    QHBoxLayout* head_layout = new QHBoxLayout(m_head_widget);
    head_layout->setContentsMargins(0, 0, 0, 0);
    head_layout->setSpacing(5);
    head_layout->addWidget(m_icon_label);
    head_layout->addWidget(m_title_label);
    head_layout->addStretch();
    head_layout->addWidget(m_min_button);
    head_layout->addWidget(m_max_button);
    head_layout->addWidget(m_close_button);

    m_body_layout = new QHBoxLayout(m_body_widget);
    m_body_layout->setContentsMargins(0, 0, 0, 0);
    m_body_layout->setSpacing(0);

    m_layout = new QVBoxLayout(this);
    m_layout->setContentsMargins(MarginSize, MarginSize, MarginSize, MarginSize);
    m_layout->setSpacing(0);
    m_layout->addWidget(m_main_widget);

    QVBoxLayout* layout = new QVBoxLayout(m_main_widget);
    layout->setContentsMargins(0, 0, 0, 0);
    layout->setSpacing(0);
    layout->addWidget(m_head_widget);
    layout->addWidget(m_body_widget);
    layout->addWidget(m_foot_widget);

    // 设置最小尺寸
    setMinimumSize(400, 300);
}

void FramelessWindow::setupWindowControls()
{
    connect(m_min_button, &QPushButton::clicked, this, &FramelessWindow::minimizeWindow);
    connect(m_max_button, &QPushButton::clicked, this, &FramelessWindow::toggleMaximize);
    connect(m_close_button, &QPushButton::clicked, this, &FramelessWindow::closeWindow);
}

bool FramelessWindow::isInTitleBarArea(const QPointF& pos)
{
    return m_head_widget->geometry().contains(pos.toPoint());
}

bool FramelessWindow::isInResizeArea(const QPointF& pos)
{
    const int resizeMargin = 7;

    if (isMaximized())
    {
        return false;
    }
    else if (pos.x() < resizeMargin)
    {
        if (pos.y() < resizeMargin)
        {
            m_resizeEdge = TopLeft;
        }
        else if (pos.y() > height() - resizeMargin)
        {
            m_resizeEdge = BottomLeft;
        }
        else
        {
            m_resizeEdge = Left;
        }
    }
    else if (pos.x() > width() - resizeMargin)
    {
        if (pos.y() < resizeMargin)
        {
            m_resizeEdge = TopRight;
        }
        else if (pos.y() > height() - resizeMargin)
        {
            m_resizeEdge = BottomRight;
        }
        else
        {
            m_resizeEdge = Right;
        }
    }
    else if (pos.y() < resizeMargin)
    {
        m_resizeEdge = Top;
    }
    else if (pos.y() > height() - resizeMargin)
    {
        m_resizeEdge = Bottom;
    }
    else
    {
        m_resizeEdge = None;
        return false;
    }
    return true;
}

void FramelessWindow::updateCursorShape(const QPointF& pos)
{
    if (isInResizeArea(pos))
    {
        switch (m_resizeEdge)
        {
        case Top:
        case Bottom:
            setCursor(Qt::SizeVerCursor);
            break;
        case Left:
        case Right:
            setCursor(Qt::SizeHorCursor);
            break;
        case TopLeft:
        case BottomRight:
            setCursor(Qt::SizeFDiagCursor);
            break;
        case TopRight:
        case BottomLeft:
            setCursor(Qt::SizeBDiagCursor);
            break;
        default:
            setCursor(Qt::ArrowCursor);
            break;
        }
    }
    else
    {
        setCursor(Qt::ArrowCursor);
    }
}
